#include "main.h"
#include "AdminManager.h"
#include <sstream>
#include <string>
#include <time.h>


int main(int argc, char *argv[])
{
	QApplication app(argc, argv);
	Main display_main;
	display_main.show();
	return app.exec();
}

Main::MessageDestination::MessageDestination(AgoraCore::MsgTextType _type, unsigned int _id) :
type(_type), id(_id)
{
}

Main::Main() :
_audioInStarted(true),
_audioOutStarted(true),
_encoderKey(SPEEX),
_freq(NARROWBAND),
_format(STEREO16),
_qualityAudio(5),
cnxWindow(NULL),
newWindow(NULL),
channelPropertiesWindow(NULL),
crtChannelWindow(NULL),
enterPasswordWindow(NULL),
_isConnected(false),
_messageTargetId(0)
{

	iconChan = new QIcon("./images/Chan.png");
	iconPeople = new QIcon("./images/Buddy.png");
	//Subscribe event
	AdminEventManager::GetAdminEventManager()->SubscribeOnEvent(AdminEventManager::ONCHANNELLISTRECEIVED, &fillTree, this);
	AdminEventManager::GetAdminEventManager()->SubscribeOnEvent(AdminEventManager::ONUSERLISTRECEIVED, &addUsers, this);
	AdminEventManager::GetAdminEventManager()->SubscribeOnEvent(AdminEventManager::ONERROR, &showError, this);
	AdminEventManager::GetAdminEventManager()->SubscribeOnEvent(AdminEventManager::ONUSERCHANNELCHANGE, &changeUserChannel, this);
	AdminEventManager::GetAdminEventManager()->SubscribeOnEvent(AdminEventManager::ONCHANNELCREATED, &onChannelCreated, this);
	AdminEventManager::GetAdminEventManager()->SubscribeOnEvent(AdminEventManager::ONCHANNELDELETED, &onChannelDeleted, this);
	AdminEventManager::GetAdminEventManager()->SubscribeOnEvent(AdminEventManager::ONUSERDISCONNECTION, &onUserDisconnection, this);
	AdminEventManager::GetAdminEventManager()->SubscribeOnEvent(AdminEventManager::ONUSERCONNECTION, &onUserConnection, this);
	AdminEventManager::GetAdminEventManager()->SubscribeOnEvent(AdminEventManager::ONUSERKICKED, &onUserKicked, this);
	AdminEventManager::GetAdminEventManager()->SubscribeOnEvent(AdminEventManager::ONUSERKICKEDFROMSERVER, &onUserKickedFromServer, this);
	AdminEventManager::GetAdminEventManager()->SubscribeOnEvent(AdminEventManager::ONUSERBANNED, &onUserBanned, this);
	AdminEventManager::GetAdminEventManager()->SubscribeOnEvent(AdminEventManager::ONUSERUNBANNED, &onUserUnbanned, this);
	AdminEventManager::GetAdminEventManager()->SubscribeOnEvent(AdminEventManager::ONUSERBANNEDLISTRECEIVED, &onUserBannedListReceived, this);
	AdminEventManager::GetAdminEventManager()->SubscribeOnEvent(AdminEventManager::ONUSERBANNEDFROMSERVERLISTRECEIVED, &onUserBannedFromServerListReceived, this);
	AdminEventManager::GetAdminEventManager()->SubscribeOnEvent(AdminEventManager::ONUSERBANNEDFROMSERVER, &onUserBannedFromServer, this);
	AdminEventManager::GetAdminEventManager()->SubscribeOnEvent(AdminEventManager::ONUSERUNBANNEDFROMSERVER, &onUserUnannedFromServer, this);
	AdminEventManager::GetAdminEventManager()->SubscribeOnEvent(AdminEventManager::ONUSERCHANNELRIGHTRECEIVED, &onUserChannelRightReceived, this);
	AdminEventManager::GetAdminEventManager()->SubscribeOnEvent(AdminEventManager::ONUSERCHANNELRIGHTEDITED, &onUserChannelRightReceived, this);
	AdminEventManager::GetAdminEventManager()->SubscribeOnEvent(AdminEventManager::ONUSERHOSTRIGHTRECEIVED, &onUserHostRightReceived, this);
	AdminEventManager::GetAdminEventManager()->SubscribeOnEvent(AdminEventManager::ONUSERHOSTRIGHTEDITED, &onUserHostRightReceived, this);
	AdminEventManager::GetAdminEventManager()->SubscribeOnEvent(AdminEventManager::ONCHANNELRIGHTRECEIVED, &onChannelRightReceived, this);
	AdminEventManager::GetAdminEventManager()->SubscribeOnEvent(AdminEventManager::ONHOSTRIGHTRECEIVED, &onHostRightReceived, this);
	AdminEventManager::GetAdminEventManager()->SubscribeOnEvent(AdminEventManager::ONUSERMESSAGERECEIVED, &onUserMessageReceived, this);
	AdminEventManager::GetAdminEventManager()->SubscribeOnEvent(AdminEventManager::ONCHANNELMESSAGERECEIVED, &onChannelMessageReceived, this);
	AdminEventManager::GetAdminEventManager()->SubscribeOnEvent(AdminEventManager::ONALLCHANNELMESSAGERECEIVED, &onAllChannelMessageReceived, this);
	AdminEventManager::GetAdminEventManager()->SubscribeOnEvent(AdminEventManager::ONCHANNELEDITED, &onChannelEdited, this);
	AdminEventManager::GetAdminEventManager()->SubscribeOnEvent(AdminEventManager::ONUSERDELETED, &onUserDeleted, this);
	AdminEventManager::GetAdminEventManager()->SubscribeOnEvent(AdminEventManager::ONUSERCREATION, &onUserCreation, this);
	AdminEventManager::GetAdminEventManager()->SubscribeOnEvent(AdminEventManager::ONUSERMUTESOUNDCHANNEL, &onUserMuteSoundChannel, this);
	AdminEventManager::GetAdminEventManager()->SubscribeOnEvent(AdminEventManager::ONUSERMUTETXTCHANNEL, &onUserMuteTxtChannel, this);
	AdminEventManager::GetAdminEventManager()->SubscribeOnEvent(AdminEventManager::ONUSERUNMUTESOUNDCHANNEL, &onUserUnmuteSoundChannel, this);
	AdminEventManager::GetAdminEventManager()->SubscribeOnEvent(AdminEventManager::ONUSERUNMUTETXTCHANNEL, &onUserUnmuteTxtChannel, this);

	// creer la base
	this->_agora = new Agora();
	_audioInKey = this->_agora->CreateDefaultMicro(_freq, _format);
	this->_agora->SetVoiceActivityDetection(_audioInKey, true);
	this->_agora->CreateDefaultAudioOut();
	this->_agora->CreateDefaultEncoder(_qualityAudio, _encoderKey);
	this->_agora->SetEncoderForAudioInput(_encoderKey, _audioInKey);
	this->_agora->CreateDefaultEmpacter();
	this->_agora->CreateDefaultClient();
	this->_agora->SetSpacialInfoAll(0, 0, 0, 
		0, 0, 0, 
		0, 0, 0);


	setWindowIcon(QIcon("./images/Agora.png"));

	///// MENU //

	QWidget *central = new QWidget();
	QVBoxLayout *layout = new QVBoxLayout(central);
	setCentralWidget(central);

	//menu = new QMenuBar(this);
	//menu->setGeometry(0, 0, 200,20);

	fileMenu = menuBar()->addMenu(tr("&File"));
	actionFile1 = new QAction(tr("&Connect"), this);
	actionFile1->setShortcut(tr("Alt+C"));
	actionFile1->setStatusTip(tr("Connect to network"));
	fileMenu->addAction(actionFile1);
	actionFile2 = new QAction(tr("&Quit"), this);
	actionFile2->setShortcut(tr("Alt+F4"));
	actionFile2->setStatusTip(tr("Quit application"));
	fileMenu->addAction(actionFile2);
	//	menu->addMenu(fileMenu);

	propertiesMenu = menuBar()->addMenu(tr("&Properties"));
	actionProperties = new QAction(tr("&Manage"), this);
	actionProperties->setShortcut(tr("Alt+G"));
	actionProperties->setStatusTip(tr("Manage Channel"));
	propertiesMenu->addAction(actionProperties);
	//	menu->addMenu(propertiesMenu);


	aboutMenu = menuBar()->addMenu(tr("&About"));
	actionAbout1 = new QAction(QIcon("./images/Agora.png"), tr("&Us"), this);
	actionAbout2 = new QAction(QIcon("./images/Epitech.png"), tr("&Epitech"), this);
	aboutMenu->addAction(actionAbout1);
	aboutMenu->addAction(actionAbout2);
	//menuBar()->addMenu(aboutMenu);



	modele = new QStandardItemModel(this);

	vue = new myQTreeView(this);
	vue->setModel(modele);
	vue->setContextMenuPolicy(Qt::CustomContextMenu);
	connect(vue, SIGNAL(customContextMenuRequested(const QPoint&)),this, SLOT(ShowTreeContextMenu(const QPoint&)));

	QGroupBox* bandwidthBox = new QGroupBox(this);
	bandwidthBox->setTitle("Used Bandwidth");
	acquisition = new QLabel("Upload : 0 Ko/sec");
	reception = new QLabel("Download : 0 Ko/sec");
	QHBoxLayout* bandwidth = new QHBoxLayout;
	bandwidth->addWidget(acquisition);
	bandwidth->addWidget(reception);
	bandwidthBox->setLayout(bandwidth);
	messageBox = new QTextEdit(this);
	messageBox->setReadOnly(true);

	QHBoxLayout* sendMessageLayout = new QHBoxLayout();
	QWidget*	sendMessageWidget = new QWidget();
	sendMessageTarget = new QComboBox(this);
	this->_mapMessageDestination[_messageTargetId++] = MessageDestination(AgoraCore::MSGALLCHANNEL, 0);
	this->sendMessageTarget->addItem(*iconChan, "All Channels", QVariant(_messageTargetId - 1));
	sendMessageTarget->setMinimumWidth(200);

	message = new QLineEdit(this);
	message->setMinimumWidth(400);
	sendText = new QPushButton(tr("Send"), this);
	connect(sendText, SIGNAL(clicked()), this, SLOT(sendMessage()));
	this->sendText->setEnabled(false);
	sendMessageLayout->addWidget(sendMessageTarget);
	sendMessageLayout->addWidget(message);
	sendMessageLayout->addWidget(sendText);
	sendMessageWidget->setLayout(sendMessageLayout);



	QTimer *timer = new QTimer(this);
	connect(timer, SIGNAL(timeout()), this, SLOT(updateBandwidth()));
	timer->start(1500);

	vue->header()->hide();
	layout->addWidget(vue);
	layout->addWidget(messageBox);
	layout->addWidget(sendMessageWidget);

	layout->addWidget(bandwidthBox);

	connect(actionFile1, SIGNAL(triggered()), this, SLOT(connectNetwork()));
	connect(actionFile2, SIGNAL(triggered()), qApp, SLOT(quit()));
	connect(actionProperties, SIGNAL(triggered()), this, SLOT(showGeneralProperties()));
	connect(this, SIGNAL(error(QString)), this, SLOT(showErrorGUIThread(QString)));
	connect(this, SIGNAL(removeChannelSig(unsigned int)), this, SLOT(removeChannelGUI(unsigned int)));
	connect(this, SIGNAL(messageToMessageBox(std::string*, std::string*, std::string*, std::string*)), this, SLOT(addMessageToMessageBoxGUIThread(std::string*, std::string*, std::string*, std::string*)));
	connect(this, SIGNAL(addUserSig(unsigned int, unsigned int, std::string*)), this, SLOT(addUserGUI(unsigned int, unsigned int, std::string*)));
	connect(this, SIGNAL(removeUserSig(unsigned int)), this, SLOT(removeUserGUI(unsigned int)));
	connect(this, SIGNAL(addChannelSig(unsigned int, unsigned int, std::string *)), this, SLOT(addChannelGUI(unsigned int, unsigned int, std::string *)));
	connect(this, SIGNAL(editChannelSig(IChannel *)), this, SLOT(editChannelGUI(IChannel *)));
	
	messageBox->setText("<a style=\"color:#000000\"><b>Messages from server :</b></a>");
	setFocusPolicy(Qt::StrongFocus);
	this->_agora->StartAudioInput();
	this->_agora->StartAudioOut();
}

void Main::keyPressEvent(QKeyEvent *e)
{
	if (_pushToTalk)
	{
		if (e->key() == this->_pushtoTalkKey && _audioInStarted)
		{
			this->GetAgora()->StartAudioInput();
		}
	}
	if ((e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) && this->_isConnected && this->message->text().size())
		this->sendMessage();
	QMainWindow::keyPressEvent(e);
}

void Main::keyReleaseEvent(QKeyEvent * e)
{
	if (_pushToTalk)
	{
		if (e->key() == this->_pushtoTalkKey && _audioInStarted)
		{
			this->GetAgora()->StopAudioInput();
		}
	}
	QMainWindow::keyReleaseEvent(e);
}

void Main::addMessageToMessageBoxGUIThread(std::string* title, std::string* message, std::string* colorTitle, std::string* colorMessage)
{
	std::string toAppend("<a style=\"color:");
	toAppend.append(*colorTitle);
	toAppend.append("\"><b>");
	toAppend.append(*title);
	toAppend.append(" : </b></a><a style=\"color:");
	toAppend.append(*colorMessage);
	toAppend.append("\">");
	toAppend.append(*message);
	toAppend.append("</a>");
	messageBox->append(toAppend.c_str());
	messageBox->moveCursor(QTextCursor::Down);
	delete title;
	delete colorTitle;
	delete message;
	delete colorMessage;
}

void Main::addMessageToMessageBox(std::string* title, std::string* message, std::string* colorTitle, std::string* colorMessage)
{
	emit this->messageToMessageBox(title, message, colorTitle, colorMessage);
}

void Main::updateBandwidth()
{
	std::ostringstream stream;
	std::ostringstream stream2;


	stream << "Upload : " << (((float)this->_agora->GetUploadRate()) / 1000) << " Ko/sec";
	acquisition->setText(stream.str().c_str());
	stream2 << "Download : " << (((float)this->_agora->GetDownloadRate()) / 1000) << " Ko/sec";
	reception->setText(stream2.str().c_str());
	if (!this->_agora->IsConnected() && IsConnected())
	{
		SetConnected(false);
	}
}

// TODO !!!! MOVE TO OBJECT MAIN (c != c++)
QStandardItem *GetItem(QModelIndex index, QStandardItem *item)
{
	if (item->index() == index)
		return item;
	int end = item->rowCount();
	for (int i = 0; i < end; i++)
	{
		QStandardItem *it = item->child(i);
		if (it->index() == index)
		{
			return it;
		}
		else
		{
			QStandardItem *it2 = GetItem(index, it);
			if (it2)
				return it2;
		}
	}
	return 0;
}

QStandardItem *Main::getSelectedItem()
{
	QItemSelectionModel *selection = vue->selectionModel();
	QModelIndex indexElementSelectionne = selection->currentIndex();
	return GetItem(indexElementSelectionne, this->_mapIdChannel[0]);
}

void Main::ShowTreeContextMenu(const QPoint& pnt)
{
	QModelIndex index = this->vue->indexAt(pnt);
	if (index.isValid())
	{

		QStandardItem *item = GetItem(index, this->_mapIdChannel[0]);
		if (item->icon().serialNumber() == iconChan->serialNumber())
		{
			QMenu menu(this);
			QAction *action = menu.addAction("Move to this channel");
			connect(action, SIGNAL(triggered()), this, SLOT(MoveToSelectedChannel()));
			//	void	JoinChannel(unsigned int channelId, const std::string& password);
			action = menu.addAction("Delete this Channel");
			connect(action, SIGNAL(triggered()), this, SLOT(DeleteChannel()));
			if (this->_mapChannelId[item] == 0)
			{
				action->setDisabled(true);
			}
			action = menu.addAction("Create a Sub-Channel");
			connect(action, SIGNAL(triggered()), this, SLOT(OpenCreateChanWindow()));
			action = menu.addAction("Properties");
			connect(action, SIGNAL(triggered()), this, SLOT(OpenChannelPropertiesWindow()));
			menu.exec(QCursor::pos());
		}
		else if (item->icon().serialNumber() == iconPeople->serialNumber())
		{
			QMenu menu(this);
			QAction *action=menu.addAction("Kick this User from his channel");
			if (!(this->_hostRight->GetCanKickUser() || this->_channelRights[this->_mapChannelId[getSelectedItem()->parent()]]->GetCanKickUser()))
				action->setDisabled(true);			
			connect(action, SIGNAL(triggered()), this, SLOT(KickSelectedUser()));
			action=menu.addAction("Kick this User from the server");
			if (!this->_hostRight->GetCanKickUser())
				action->setDisabled(true);
			connect(action, SIGNAL(triggered()), this, SLOT(KickSelectedUserFromServer()));
			menu.exec(QCursor::pos());
		}

	}
}

void Main::DeleteChannel()
{
	AdminManager::GetAdminManager()->DeleteChannel(this->_mapChannelId[getSelectedItem()]);
}

void Main::KickSelectedUser()
{
	AdminManager::GetAdminManager()->KickUser(this->_mapUserId[getSelectedItem()], this->_mapChannelId[getSelectedItem()->parent()]);
}

void Main::KickSelectedUserFromServer()
{
	AdminManager::GetAdminManager()->KickUserFromServer(this->_mapUserId[getSelectedItem()]);

}


void Main::addItem(QStandardItem* it, unsigned int idParent, unsigned int id)
{
	it->setEditable(false);
	if (id == 0)
	{
		this->modele->appendRow(it);
	}
	else if (this->_mapIdChannel.count(idParent))
	{
		this->_mapIdChannel[idParent]->appendRow(it);
	}
}

void Main::addChannel(unsigned int idParent, unsigned int id, std::string name)
{
	emit this->addChannelSig(idParent, id, new std::string(name));
}

void Main::addChannelGUI(unsigned int idParent, unsigned int id, std::string *name)
{
	AdminManager::GetAdminManager()->GetChannelBannedUsers(id);
	QStandardItem* it = new QStandardItem(*iconChan, name->c_str());
	addItem(it, idParent, id);
	this->_mapMessageDestination[_messageTargetId++] = (MessageDestination(AgoraCore::MSGCHANNEL, id));
	std::string tmp;
	if (id != 0)
	{
		tmp = this->_mapIdIChannel[idParent]->GetName() + ":" + *name;
	}
	else
		tmp = *name;
	this->sendMessageTarget->addItem(*iconChan, tmp.c_str(), QVariant(_messageTargetId - 1));
	this->_mapIdChannel[id] = it;
	this->_mapChannelId[it] = id;
	delete name;
}

bool Main::IsUserAddToMessageTarget(unsigned int id)
{
	std::map<int, MessageDestination>::iterator it = this->_mapMessageDestination.begin();
	std::map<int, MessageDestination>::iterator itend = this->_mapMessageDestination.end();
	for (; it != itend; ++it)
	{
		if (it->second.type == AgoraCore::MSGUSER && it->second.id == id)
			return true;
	}
	return false;
}

void Main::addUser(unsigned int idParent, unsigned int id, std::string name)
{
	if (!this->IsUserAddToMessageTarget(id))
	{
		this->_mapMessageDestination[this->_messageTargetId++] = (MessageDestination(AgoraCore::MSGUSER, id));
		this->sendMessageTarget->insertItem(0, *(this->iconPeople), name.c_str(), QVariant(this->_messageTargetId - 1));
	}
	emit this->addUserSig(idParent, id, new std::string(name));
}

void Main::addUserGUI(unsigned int idParent, unsigned int id, std::string *name)
{
	std::map<unsigned int, QStandardItem*>::iterator it = this->_mapIdUser.begin();
	std::map<unsigned int, QStandardItem*>::iterator itend = this->_mapIdUser.end();

	for (;it != itend; ++it)
	{
		if (it->first == id)
			return;
	}

	if (!this->_mapIdChannel.count(idParent))
		return;
	QStandardItem* item = new QStandardItem(*iconPeople, name->c_str());
	addItem(item, idParent, -1);

	this->_mapIdUser[id] = item;
	this->_mapUserId[item] = id;
	delete name;
}

void Main::removeChannel(unsigned int id)
{
	QStandardItem* item = this->_mapIdChannel[id];

	int end = item->rowCount();
	for (int i = 0; i < end; i++)
	{
		QStandardItem *it = item->child(i);
		if (it->icon().serialNumber() == iconChan->serialNumber())
		{
			removeChannel(this->_mapChannelId[it]);
		}
	}

	this->_mapChannelId.erase(item);
	this->_mapIdIChannel.erase(id);	
	emit this->removeChannelSig(id);
}

void Main::removeChannelGUI(unsigned int id)
{
	if (id != 0)
	{
		QStandardItem* item = this->_mapIdChannel[id];
		item->parent()->removeRow(item->row());
		this->_mapIdChannel.erase(id);
		std::map<int, MessageDestination>::iterator it = this->_mapMessageDestination.begin();
		std::map<int, MessageDestination>::iterator itend = this->_mapMessageDestination.end();
		int toDel = -1;
		for(; it != itend; ++it)
		{
			if (it->second.type == MSGCHANNEL && it->second.id == id)
			{
				toDel = it->first;
				break;
			}
		}
		if (toDel > 0)
		{
			int idx = this->sendMessageTarget->findData(toDel);
			this->sendMessageTarget->removeItem(idx);
			this->_mapMessageDestination.erase(toDel);
		}
	}
}

void Main::showGeneralProperties()
{
	if (newWindow == NULL)
	{
		newWindow = new secondWindow(this);
	}
	newWindow->showNormal();
	newWindow->reload();
	newWindow->SetGetKey(false);
	newWindow->SetKeyText(this->_pushtoTalkKey, this->_pushtoTalkKeyText);
}


void Main::connectNetwork()
{
	if (!this->_isConnected)
	{
		if (cnxWindow == NULL)
		{
			cnxWindow = new connexionWindow(this);
		}
		cnxWindow->showNormal();
	}
	else
	{
		this->_agora->Disconnect();
		this->SetConnected(false);
	}
}

Agora* Main::GetAgora()
{
	return this->_agora;
}

bool   Main::IsAudioInStarted()
{
	return this->_audioInStarted;
}

void   Main::SetAudioInStarted(bool val)
{
	this->_audioInStarted = val;
}


bool   Main::IsAudioOutStarted()
{
	return this->_audioOutStarted;
}

void   Main::SetAudioOutStarted(bool val)
{
	this->_audioOutStarted = val;
}

void	Main::showErrorGUIThread(QString text)
{
	QMessageBox::information(0, "Error", text);
}

void Main::showError(AdminEventManager::EventArg *e, void *data)
{
	Main *m = reinterpret_cast<Main *>(data);

	//QString str = new QString()
	emit m->error(QString(e->Message.c_str()));
	//	
}

void Main::changeUserChannelInTreeView(int userId, int chanId, std::string userName)
{
	if (this->_mapIdUser.count(userId))
	{
		this->_mapIdUser[userId]->parent()->removeRow(this->_mapIdUser[userId]->row());
		this->_mapIdUser.erase(userId);
	}
	addUser(chanId, userId, userName);
}

//TODO erreur changement chan serveur :( (_currentChanId wrong)
void Main::changeUserChannel(AdminEventManager::EventArg *e, void *data)
{
	IUser *user = e->UserList.front();
	reinterpret_cast<Main *>(data)->changeUserChannelInTreeView(user->GetId(), e->ChannelTo->GetId(), user->GetLogin());
	std::string *message = new std::string(user->GetLogin());
	message->append(" has moved to channel ");
	message->append(e->ChannelTo->GetName());
	reinterpret_cast<Main *>(data)->addMessageToMessageBox(new std::string("User"), 
		message, 
		new std::string("SlateGray"), new std::string("Black"));
}

void			Main::onUserKickedFromServer(AdminEventManager::EventArg *e, void *data)
{
	IUser *user = e->UserList.front();
	std::string *message = new std::string(user->GetLogin());
	reinterpret_cast<Main *>(data)->addMessageToMessageBox(new std::string("User"), &(message->append(" has been kicked from server")), new std::string("SlateGray"), new std::string("Black"));
	emit reinterpret_cast<Main *>(data)->removeUserSig(user->GetId());
}

void			Main::onUserBannedFromServerListReceived(AdminEventManager::EventArg *e, void *data)
{
	Main *main = reinterpret_cast<Main *>(data);

	std::list<IUser*>::iterator current = e->UserList.begin();
	std::list<IUser*>::iterator end = e->UserList.end();
	for(; current != end; ++current)
	{
		main->_userServerBanned.push_back((*current)->GetId());
	}
}

void			Main::onUserBannedListReceived(AdminEventManager::EventArg *e, void *data)
{
	Main *main = reinterpret_cast<Main *>(data);
	
	IChannel *chan = e->ChannelList.front();
	std::list<IUser*>::iterator current = e->UserList.begin();
	std::list<IUser*>::iterator end = e->UserList.end();
	for(; current != end; ++current)
	{
		main->_userChannelBanned[chan->GetId()].push_back((*current)->GetId());
	}
}

void			Main::onUserBanned(AdminEventManager::EventArg *e, void *data)
{
	Main *main = reinterpret_cast<Main *>(data);

	IUser *user = e->UserList.front();
	std::string *message = new std::string(user->GetLogin());
	message->append(" has been banned from the channel ");
	message->append(e->ChannelList.front()->GetName());
	reinterpret_cast<Main *>(data)->addMessageToMessageBox(new std::string("User"), 
		message, 
		new std::string("SlateGray"), new std::string("Black"));
	main->_userChannelBanned[e->ChannelList.front()->GetId()].push_back(user->GetId());
	if (main->channelPropertiesWindow)
	{
			main->channelPropertiesWindow->reload();
	}
}

void			Main::onUserUnbanned(AdminEventManager::EventArg *e, void *data)
{
	Main *main = reinterpret_cast<Main *>(data);

	IUser *user = e->UserList.front();
	std::string *message = new std::string(user->GetLogin());
	message->append(" has been unbanned from the channel ");
	message->append(e->ChannelList.front()->GetName());
	reinterpret_cast<Main *>(data)->addMessageToMessageBox(new std::string("User"), 
		message, 
		new std::string("SlateGray"), new std::string("Black"));
	main->_userChannelBanned[e->ChannelList.front()->GetId()].remove(user->GetId());
	if (main->channelPropertiesWindow)
	{
			main->channelPropertiesWindow->reload();
	}
}

void			Main::onUserBannedFromServer(AdminEventManager::EventArg *e, void *data)
{
	Main *main = reinterpret_cast<Main *>(data);

	IUser *user = e->UserList.front();
	std::string *message = new std::string(user->GetLogin());
	message->append(" has been banned from the server");
	reinterpret_cast<Main *>(data)->addMessageToMessageBox(new std::string("User"), 
		message, 
		new std::string("SlateGray"), new std::string("Black"));
	main->_userServerBanned.push_back(user->GetId());
	if (main->newWindow)
	{
			main->newWindow->reload();
	}
}

void			Main::onUserUnannedFromServer(AdminEventManager::EventArg *e, void *data)
{
	Main *main = reinterpret_cast<Main *>(data);

	IUser *user = e->UserList.front();
	std::string *message = new std::string(user->GetLogin());
	message->append(" has been unbanned from the server");
	reinterpret_cast<Main *>(data)->addMessageToMessageBox(new std::string("User"), 
		message, 
		new std::string("SlateGray"), new std::string("Black"));
	main->_userServerBanned.remove(user->GetId());
	if (main->newWindow)
	{
			main->newWindow->reload();
	}
}

void Main::onUserMuteSoundChannel(AdminEventManager::EventArg *e, void *data)
{
	Main *main = reinterpret_cast<Main *>(data);

	IUser *user = e->UserList.front();
	std::string *message = new std::string(user->GetLogin());
	message->append(" cannot talk anymore in channel ");
	message->append(e->ChannelList.front()->GetName());
	reinterpret_cast<Main *>(data)->addMessageToMessageBox(new std::string("User"), 
		message, 
		new std::string("firebrick"), new std::string("firebrick"));
	main->_userServerBanned.remove(user->GetId());
}

void Main::onUserMuteTxtChannel(AdminEventManager::EventArg *e, void *data)
{
	Main *main = reinterpret_cast<Main *>(data);

	IUser *user = e->UserList.front();
	std::string *message = new std::string(user->GetLogin());
	message->append(" cannot send text messages anymore in channel ");
	message->append(e->ChannelList.front()->GetName());
	reinterpret_cast<Main *>(data)->addMessageToMessageBox(new std::string("User"), 
		message, 
		new std::string("firebrick"), new std::string("firebrick"));
	main->_userServerBanned.remove(user->GetId());
}

void Main::onUserUnmuteSoundChannel(AdminEventManager::EventArg *e, void *data)
{
	Main *main = reinterpret_cast<Main *>(data);

	IUser *user = e->UserList.front();
	std::string *message = new std::string(user->GetLogin());
	message->append(" can talk in channel ");
	message->append(e->ChannelList.front()->GetName());
	reinterpret_cast<Main *>(data)->addMessageToMessageBox(new std::string("User"), 
		message, 
		new std::string("ForestGreen"), new std::string("ForestGreen"));
	main->_userServerBanned.remove(user->GetId());
}

void Main::onUserUnmuteTxtChannel(AdminEventManager::EventArg *e, void *data)
{
	Main *main = reinterpret_cast<Main *>(data);

	IUser *user = e->UserList.front();
	std::string *message = new std::string(user->GetLogin());
	message->append(" can send text messages in channel ");
	message->append(e->ChannelList.front()->GetName());
	reinterpret_cast<Main *>(data)->addMessageToMessageBox(new std::string("User"), 
		message, 
		new std::string("ForestGreen"), new std::string("ForestGreen"));
	main->_userServerBanned.remove(user->GetId());
}

void Main::onChannelDeleted(AdminEventManager::EventArg *e, void *data)
{
	if (e->ChannelList.size() > 0)
	{
		std::string *message = new std::string("channel deleted : ");
		IChannel* chan = e->ChannelList.front();
		if (reinterpret_cast<Main *>(data)->channelPropertiesWindow && 
			reinterpret_cast<Main *>(data)->channelPropertiesWindow->GetChannel() == chan)
		{
			reinterpret_cast<Main *>(data)->channelPropertiesWindow->SetChannel(0);
		}
		reinterpret_cast<Main *>(data)->removeChannel(chan->GetId());
		reinterpret_cast<Main *>(data)->addMessageToMessageBox(new std::string("Channel"), &(message->append(chan->GetName())), new std::string("SlateGray"), new std::string("Black"));
	}
}

void Main::removeUserGUI(unsigned int id)
{
	this->_mapIdUser[id]->parent()->removeRow(this->_mapIdUser[id]->row());
	this->_mapIdUser.erase(id);
	std::map<int, MessageDestination>::iterator it = this->_mapMessageDestination.begin();
	std::map<int, MessageDestination>::iterator itend = this->_mapMessageDestination.end();
	int toDel = -1;
	for(; it != itend; ++it)
	{
		if (it->second.type == MSGUSER && it->second.id == id)
		{
			toDel = it->first;
			break;
		}
	}
	if (toDel > 0)
	{
		int idx = this->sendMessageTarget->findData(toDel);
		this->sendMessageTarget->removeItem(idx);
		this->_mapMessageDestination.erase(toDel);
	}
}

void Main::onUserDisconnection(AdminEventManager::EventArg *e, void *data)
{
	if (e->UserList.size() > 0)
	{
		IUser* user = e->UserList.front();
		if (reinterpret_cast<Main *>(data)->_mapIdUser.count(user->GetId()))
		{
			std::string *message = new std::string(user->GetLogin());
			message->append(" is disconnected");
			reinterpret_cast<Main *>(data)->addMessageToMessageBox(new std::string("User"), 
			message, 
			new std::string("SlateGray"), new std::string("Black"));
			emit reinterpret_cast<Main *>(data)->removeUserSig(user->GetId());
			
		}
	}
}

void Main::onUserKicked(AdminEventManager::EventArg *e, void *data)
{
	if (e->UserList.size() > 0)
	{
		IUser* user = e->UserList.front();
		if (reinterpret_cast<Main *>(data)->_mapIdUser.count(user->GetId()))
		{
			reinterpret_cast<Main *>(data)->_mapIdUser[user->GetId()]->parent()->removeRow(reinterpret_cast<Main *>(data)->_mapIdUser[user->GetId()]->row());
			reinterpret_cast<Main *>(data)->_mapIdUser.erase(user->GetId());	
		}
		reinterpret_cast<Main *>(data)->addUser(0, user->GetId(), user->GetLogin());
	}
}


void Main::onUserConnection(AdminEventManager::EventArg *e, void *data)
{
	if (e->UserList.size() > 0)
	{
		IUser* user = e->UserList.front();
		std::string *message = new std::string(user->GetLogin());
		message->append(" is connected");
		reinterpret_cast<Main *>(data)->addMessageToMessageBox(new std::string("User"), 
		message, 
		new std::string("SlateGray"), new std::string("Black"));
		reinterpret_cast<Main *>(data)->addIUser(user);
		reinterpret_cast<Main *>(data)->addUser(0, user->GetId(), user->GetLogin());
	}
}

void Main::onChannelCreated(AdminEventManager::EventArg *e, void *data)
{
	if (e->ChannelList.size() > 0)
	{
		std::string *message = new std::string("channel created : ");
		IChannel* chan = e->ChannelList.front();
		reinterpret_cast<Main *>(data)->addIChannel(chan);
		reinterpret_cast<Main *>(data)->addChannel(chan->GetIdParent(), chan->GetId(), chan->GetName());
		reinterpret_cast<Main *>(data)->addMessageToMessageBox(new std::string("Channel"), &(message->append(chan->GetName())), new std::string("SlateGray"), new std::string("Black"));
	}
}

void Main::fillTree(AdminEventManager::EventArg *e, void *data)
{
	Main *m = reinterpret_cast<Main *>(data);

	std::list<IChannel*>::iterator current;
	std::list<IChannel*>::iterator end;

	current = e->ChannelList.begin();
	end = e->ChannelList.end();
	while (current != end)
	{
		reinterpret_cast<Main *>(data)->addIChannel(*current);
		m->addChannel((*current)->GetIdParent(), (*current)->GetId(), (*current)->GetName());
		++current;
	}
}

void Main::addUsers(AdminEventManager::EventArg *e, void *data)
{
	Main *m = reinterpret_cast<Main *>(data);

	std::list<IUser*>::iterator current;
	std::list<IUser*>::iterator end;

	current = e->UserList.begin();
	end = e->UserList.end();
	while (current != end)
	{
		// TODO add all user to a map
		reinterpret_cast<Main *>(data)->addIUser((*current));
		if ((*current)->IsConnected()) 
			m->addUser((*current)->GetCurrentChannelId(), (*current)->GetId(), (*current)->GetLogin());
		current++;
	}
}

int	Main::getAudioInKey()
{
	return this->_audioInKey;
}


void Main::MoveToSelectedChannel()
{
	QStandardItem* it = getSelectedItem();
	unsigned int id;
	if (this->_mapChannelId.count(it) && this->_mapIdIChannel.count(id = this->_mapChannelId[it]))
	{
		if (!this->_mapIdIChannel[id]->HasPassword())
			AdminManager::GetAdminManager()->JoinChannel(id, "");
		else
		{
			if (enterPasswordWindow == NULL)
			{
				enterPasswordWindow = new EnterPasswordWindow(this);
			}
			QString title("Join Channel ");
			enterPasswordWindow->setChannelId(id);
			enterPasswordWindow->setWindowTitle(this->_mapIdIChannel[id]->GetName().c_str());
			enterPasswordWindow->showNormal();
		}
	}
}

void Main::MoveToSelectedChannelWithPass(unsigned int channelId, const std::string &Password)
{
	AdminManager::GetAdminManager()->JoinChannel(channelId, Password);
}



void Main::OpenCreateChanWindow()
{
	if (crtChannelWindow == NULL)
	{
		crtChannelWindow = new CreateChannelWindow(this);
	}
	QStandardItem* it =  getSelectedItem();
	QString title("Add a Subchannel to ");
	crtChannelWindow->setParentChannelId(this->_mapChannelId[it]);
	crtChannelWindow->setWindowTitle(title.append(it->text()));
	crtChannelWindow->showNormal();
}

void Main::OpenChannelPropertiesWindow()
{
	if (channelPropertiesWindow == NULL)
	{
		channelPropertiesWindow = new ChannelPropertiesWindow(this);
	}
	QStandardItem* it =  getSelectedItem();
	channelPropertiesWindow->SetChannel(this->_mapIdIChannel[this->_mapChannelId[it]]);
	channelPropertiesWindow->reload();
	channelPropertiesWindow->showNormal();
}

void Main::createChannel(std::string name, std::string password, std::string motd, std::string desc, int parentChannelId)
{
	AdminManager::GetAdminManager()->AddChannel(name, password, 200, 200, motd, 200, desc, 200, true, 200,200, parentChannelId);
}

void Main::addIUser(IUser *user)
{
	this->_mapIdIUser[user->GetId()] = user;
	std::map<unsigned int, IChannel*>::iterator it = this->_mapIdIChannel.begin();
	std::map<unsigned int, IChannel*>::iterator itend = this->_mapIdIChannel.end();
	AdminManager::GetAdminManager()->GetUserHostRight(user->GetId());
	for(;it != itend; ++it)
	{
		AdminManager::GetAdminManager()->GetUserChannelRight(it->first, user->GetId());
	}
}

void Main::addIChannel(IChannel *channel)
{
	this->_mapIdIChannel[channel->GetId()] = channel;
	std::map<unsigned int, IUser*>::iterator it = this->_mapIdIUser.begin();
	std::map<unsigned int, IUser*>::iterator itend = this->_mapIdIUser.end();
	AdminManager::GetAdminManager()->GetChannelRight(channel->GetId());
	for(;it != itend; ++it)
	{
		AdminManager::GetAdminManager()->GetUserChannelRight(channel->GetId(), it->first);
	}
}

void Main::onUserChannelRightReceived(AdminEventManager::EventArg *e, void *data)
{
	Main* main = reinterpret_cast<Main *>(data);

	if (e->UserList.size())
	{
		std::map<unsigned int, IChannelRight*>::iterator it = e->ChannelRights.begin();
		std::map<unsigned int, IChannelRight*>::iterator itend = e->ChannelRights.end();
		unsigned int id = -1;
		for(;it != itend; ++it)
		{
			if (id < 0 || id != it->first)
				AdminManager::GetAdminManager()->GetChannelRight(it->first);
			id = it->first;
			main->_userChannelRights[e->UserList.front()->GetId()][it->first] = it->second;
		}
		if (main->channelPropertiesWindow)
		{
			main->channelPropertiesWindow->reload();
		}

	}
}


void Main::onUserHostRightReceived(AdminEventManager::EventArg *e, void *data)
{
	Main* main = reinterpret_cast<Main *>(data);
	if (e->UserList.size())
	{
		main->_userHostRight[e->UserList.front()->GetId()] = e->UserHostRight;
	}
	AdminManager::GetAdminManager()->GetHostRight();
	if (main->newWindow)
	{
		main->newWindow->reload();
	}
}

void Main::onChannelRightReceived(AdminEventManager::EventArg *e, void *data)
{
	Main* main = reinterpret_cast<Main *>(data);
	std::map<unsigned int, IChannelRight*>::iterator it = e->ChannelRights.begin();
	std::map<unsigned int, IChannelRight*>::iterator itend = e->ChannelRights.end();
	for(;it != itend; ++it)
	{
		main->_channelRights[it->first] = it->second;
	}
	if (main->channelPropertiesWindow)
	{
		main->channelPropertiesWindow->reload();
	}
}

void Main::onUserMessageReceived(AdminEventManager::EventArg *e, void *data)
{
	Main* main = reinterpret_cast<Main *>(data);

	if (e->UserList.size() > 1)
	{
		time_t rawtime;
		struct tm * timeinfo;
		char buffer [10];
		time ( &rawtime );
		timeinfo = localtime(&rawtime);
		strftime (buffer,10,"%X",timeinfo);

		std::string *title = new std::string("[");
		title->append(buffer,0,8);
		title->append("][From ");
		title->append(e->UserList.front()->GetLogin());
		title->append("]");
		main->addMessageToMessageBox(title, new std::string(e->Message), new std::string("DarkViolet"), new std::string("DarkViolet"));
	}
}

void Main::onChannelMessageReceived(AdminEventManager::EventArg *e, void *data)
{
	Main* main = reinterpret_cast<Main *>(data);

	if (e->UserList.size() && e->ChannelList.size())
	{
		time_t rawtime;
		struct tm * timeinfo;
		char buffer [10];
		time ( &rawtime );
		timeinfo = localtime(&rawtime);
		strftime (buffer,10,"%X",timeinfo);

		std::string *title = new std::string("[");
		title->append(buffer,0,8);
		title->append("][");
		title->append(e->ChannelList.front()->GetName());
		title->append("][");
		title->append(e->UserList.front()->GetLogin());
		title->append("]");
		main->addMessageToMessageBox(title, new std::string(e->Message), new std::string("MidnightBlue"), new std::string("MidnightBlue"));
	}
}

void Main::onUserDeleted(AdminEventManager::EventArg *e, void *data)
{
	Main* main = reinterpret_cast<Main *>(data);

	if (e->UserList.size())
	{
		Main::onUserDisconnection(e, data);
		unsigned int id = e->UserList.front()->GetId();
		std::map<unsigned int, std::list<unsigned int> >::iterator it = main->_userChannelBanned.begin();
		std::map<unsigned int, std::list<unsigned int> >::iterator itend = main->_userChannelBanned.end();
		for(; it != itend; ++it)
		{
			it->second.remove(id);
		}
		main->_userServerBanned.remove(id);

		main->_mapIdIUser.erase(id);
		main->_userChannelRights.erase(id);
		main->_userHostRight.erase(id);
		if (main->newWindow)
		{
			main->newWindow->reload();
		}
		if (main->channelPropertiesWindow)
		{
			main->channelPropertiesWindow->reload();
		}
	}
}

void Main::onUserCreation(AdminEventManager::EventArg *e, void *data)
{
	Main* main = reinterpret_cast<Main *>(data);

	if (e->UserList.size())
	{
		main->addIUser(e->UserList.front());
		if (main->newWindow)
		{
			main->newWindow->reload();
		}
		if (main->channelPropertiesWindow)
		{
			main->channelPropertiesWindow->reload();
		}
	}
}

void Main::onAllChannelMessageReceived(AdminEventManager::EventArg *e, void *data)
{
	Main* main = reinterpret_cast<Main *>(data);

	if (e->UserList.size())
	{
		time_t rawtime;
		struct tm * timeinfo;
		char buffer [10];
		time ( &rawtime );
		timeinfo = localtime(&rawtime);
		strftime (buffer,10,"%X",timeinfo);

		std::string *title = new std::string("[");
		title->append(buffer,0,8);
		title->append("][All Channels][From ");
		title->append(e->UserList.front()->GetLogin());
		title->append("]");
		main->addMessageToMessageBox(title, new std::string(e->Message), new std::string("SaddleBrown"), new std::string("SaddleBrown"));
	}
}

void Main::editChannelGUI(IChannel *channel)
{
	this->_mapIdChannel[channel->GetId()]->setText(channel->GetName().c_str());
}

void Main::onChannelEdited(AdminEventManager::EventArg *e, void *data)
{

	emit reinterpret_cast<Main *>(data)->editChannelSig(e->ChannelList.front());
	if (reinterpret_cast<Main *>(data)->channelPropertiesWindow)
	{
		reinterpret_cast<Main *>(data)->channelPropertiesWindow->reload();
	}
}

void Main::onHostRightReceived(AdminEventManager::EventArg *e, void *data)
{
	Main* main = reinterpret_cast<Main *>(data);
	main->_hostRight = e->UserHostRight;
	if (main->newWindow)
	{
		main->newWindow->reload();
	}
}

void Main::SetConnected(bool value)
{
	if (this->_isConnected && !value)
	{
		this->_isConnected = false;
		this->sendMessageTarget->clear();
		_messageTargetId = 0;
		this->_mapMessageDestination.clear();
		this->_mapMessageDestination[_messageTargetId++] = MessageDestination(AgoraCore::MSGALLCHANNEL, 0);
		this->sendMessageTarget->addItem(*iconChan, "All Channels", QVariant(_messageTargetId - 1));
		this->_mapChannelId.clear();
		this->_mapIdChannel.clear();
		this->_mapIdIChannel.clear();
		this->_mapIdIUser.clear();
		this->_mapIdUser.clear();
		this->_mapUserId.clear();
		this->_userHostRight.clear();
		this->modele->clear();
		this->_channelRights.clear();
		this->_hostRight = 0;	
		AdminManager::GetAdminManager()->ClearData();
		this->addMessageToMessageBox(new std::string("Connection"), new std::string("disconnected"), new std::string("firebrick"), new std::string("firebrick"));
		if (this->channelPropertiesWindow)
		{
			this->channelPropertiesWindow->SetChannel(0);
			this->channelPropertiesWindow->reload();
		}
		if (this->newWindow)
			this->newWindow->reload();
	}
	else
		this->_isConnected = true;
	this->sendText->setEnabled(value);
	if (value)
	{
		this->actionFile1->setText("Disconnect");
		this->actionFile1->setStatusTip(tr("Disconnect from network"));
	}
	else
	{
		this->actionFile1->setText("Connect");
		this->actionFile1->setStatusTip(tr("Connect to network"));
	}
	
}

bool Main::IsBanned(unsigned int userId)
{
	std::list<unsigned int>::iterator it = this->_userServerBanned.begin();
	std::list<unsigned int>::iterator itend = this->_userServerBanned.end();
	for(; it != itend; ++it)
	{
		if (userId == *it)
			return true;
	}
	return false;
}

bool Main::IsBanned(unsigned int userId, unsigned int chanId)
{
	std::list<unsigned int>::iterator it = this->_userChannelBanned[chanId].begin();
	std::list<unsigned int>::iterator itend = this->_userChannelBanned[chanId].end();
	for(; it != itend; ++it)
	{
		if (userId == *it)
			return true;
	}
	return false;
}

bool Main::IsConnected()
{
	return this->_isConnected;
}

void Main::SetPushToTalkKey(int value)
{
	this->_pushtoTalkKey = value;
}

void Main::SetPushToTalkKeyText(QString &value)
{
	this->_pushtoTalkKeyText = value;
}

void Main::SetPushToTalk(bool value)
{
	this->_pushToTalk = value;
}

void Main::SetVAD(bool value, unsigned short levelVoiceActivity, unsigned short timeNoCheckAfterDetection)
{
	this->_agora->SetVoiceActivityDetection(this->_audioInKey, value, levelVoiceActivity, timeNoCheckAfterDetection);
}

void Main::sendMessage()
{
	int idx = this->sendMessageTarget->itemData(this->sendMessageTarget->currentIndex()).toInt();
	AdminManager::GetAdminManager()->SendMessageType(this->_mapMessageDestination[idx].type, 
		this->_mapMessageDestination[idx].id, this->message->text().toStdString());
	this->message->setText("");
}


